﻿Imports System.IO

Public Class mainForm
    Private aliasDictionary As Dictionary(Of String, String)
    Private listItemByFileName As Dictionary(Of String, Dictionary(Of String, String))
    Private listCheckFile As List(Of String)

    Public returnDt As DataTable


#Region "Xử lí các sự kiện"

    ''' <summary>
    ''' Khởi tạo
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub mainForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        returnDt = New DataTable
        Dim col As DataColumn

        'định dạng cho data table
        col = New DataColumn()
        col.DataType = System.Type.GetType("System.String")
        col.ColumnName = "File"
        returnDt.Columns.Add(col)

        col = New DataColumn()
        col.DataType = System.Type.GetType("System.String")
        col.ColumnName = "ItemName"
        returnDt.Columns.Add(col)

        col = New DataColumn()
        col.DataType = System.Type.GetType("System.String")
        col.ColumnName = "Alias"
        returnDt.Columns.Add(col)

        loadConfiguration()
    End Sub

    ''' <summary>
    ''' Chọn thư mục
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub tbxFolder_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tbxFolder.Click
        Dim selectedPath As String = ""
        While selectedPath = ""
            chooseFolder.ShowDialog()
            selectedPath = chooseFolder.SelectedPath
        End While
        tbxFolder.Text = selectedPath
        btnLoadListItemName.PerformClick()
        If listCheckFile.Count = 0 Then
            Exit Sub
        End If
        listItemFound.DataSource = dictionanyToDataTable(listItemByFileName)
    End Sub

    ''' <summary>
    ''' Chọn xong thư mục thì cho phép click button Load
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub tbxFolder_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tbxFolder.TextChanged
        If tbxFolder.Text <> "" Then
            btnLoadListItemName.Enabled = True
        Else
            btnLoadListItemName.Enabled = False
        End If
    End Sub

    ''' <summary>
    ''' Mở file alias
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnOpenListItemName_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpenListItemName.Click
        Process.Start(config.Item(ALIAS_FILE_NAME))
    End Sub

    ''' <summary>
    ''' load lại
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnLoadListItemName_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLoadListItemName.Click

        'load file alias
        aliasDictionary = loadAliasDictionany(config.Item(ALIAS_FILE_NAME)) 'Application.StartupPath & "\" & 
        If aliasDictionary Is Nothing Then
            Me.Close()
            Exit Sub
        End If
        'lấy danh sách tên file trong thư mục vừa chọn
        listCheckFile = getListFullFileName(tbxFolder.Text, config.Item(FILE_SELECTOR))
        If listCheckFile.Count = 0 Then
            MsgBox("Không tìm được file nào phù hợp trong thư mục đã chọn!", MsgBoxStyle.Critical, "Error")
            Exit Sub
        End If
        'Danh sách đầy đủ các thuộc tính
        listItemByFileName = getListItemByFileName(listCheckFile)
    End Sub

    ''' <summary>
    ''' Show kết quả
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnExportResult_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExportResult.Click
        Result.ShowDialog()
    End Sub
#End Region

#Region "Logic chính"
    ''' <summary>
    ''' Trả về danh sách tên đầy đủ của các file trong thư mục folder theo phần mở rộng
    ''' </summary>
    ''' <param name="folderName">Tên thư mục</param>
    ''' <param name="extension">Phần mở rộng</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function getListFullFileName(ByVal folderName As String, ByVal extension As String) As List(Of String)
        Dim returnList As New List(Of String)
        Dim directoryInfo As New DirectoryInfo(folderName)
        Dim filesInfo() As FileInfo

        'duyệt và lấy tên đầy đủ của toàn bộ file trong thư mục 
        filesInfo = directoryInfo.GetFiles(extension)
        For Each fileInfo As FileInfo In filesInfo
            returnList.Add(fileInfo.FullName)
        Next fileInfo

        Return returnList
    End Function

    ''' <summary>
    ''' Duyệt list file, tìm các thuộc tính của từng file đưa vào 1 từ điển
    ''' và đưa tất cả các từ điển này vào 1 từ điển lớn 
    ''' </summary>
    ''' <param name="listFileName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function getListItemByFileName(ByVal listFileName As List(Of String)) _
                    As Dictionary(Of String, Dictionary(Of String, String))

        Dim fullDict As New Dictionary(Of String, Dictionary(Of String, String))
        Dim fileName As String = ""
        Dim itemDict As Dictionary(Of String, String)
        'tìm item trong các file vừa lấy được
        For Each checkFile As String In listFileName
            fileName = checkFile.Substring(checkFile.LastIndexOf("\") + 1)
            itemDict = getListItemInFile(checkFile, aliasDictionary)
            fullDict.Add(fileName.Trim, itemDict)
        Next checkFile
        Return fullDict
    End Function

    ''' <summary>
    ''' Duyệt file được chỉ định, tìm các thuộc tính và điền vào từ điển
    ''' </summary>
    ''' <param name="inFileName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function getListItemInFile(ByVal inFileName As String, ByVal aliasDict As Dictionary(Of String, String)) _
                    As Dictionary(Of String, String)

        Dim returnDict As New Dictionary(Of String, String)
        Dim fileContent As String
        Dim foundPos As Int32 = 0
        Dim seekPatternLength = config.Item(SEEK_PATTERN).Length
        Dim duplicateKey As String = ""
        Dim itemAlias As String = ""

        'load file
        fileContent = My.Computer.FileSystem.ReadAllText(inFileName)

        'tìm vị trí cuối cùng trong file của SEEK_PATTERN
        foundPos = fileContent.LastIndexOf(config.Item(SEEK_PATTERN))

        'lặp tìm các thuộc tính
        While foundPos > 0
            Dim itemName As String = ""

            If foundPos > 0 Then
                'Tìm dấu đóng ngoặc kép
                Dim seekQuote As Char
                Dim seekQuoteStart As Int32 = foundPos + seekPatternLength
                Dim seekQuoteEnd As Int32 = seekQuoteStart
                seekQuote = fileContent(seekQuoteEnd)
                While seekQuote <> config.Item(END_SEEK_PATTERN)
                    seekQuoteEnd += 1
                    seekQuote = fileContent(seekQuoteEnd)
                End While

                'cắt tên item

                itemName = fileContent.Substring(seekQuoteStart, seekQuoteEnd - seekQuoteStart)
                itemName = itemName.Substring(itemName.LastIndexOf(".") + 1)
                fileContent = fileContent.Remove(foundPos)

                'điền item vào từ điển
                If Not returnDict.ContainsKey(itemName) Then
                    itemAlias = getAliasFor(itemName)
                    returnDict.Add(itemName.Trim, itemAlias.Trim)
                Else
                    duplicateKey = duplicateKey & itemName & vbNewLine
                End If

            End If
            foundPos = fileContent.LastIndexOf(config.Item(SEEK_PATTERN))
        End While

        returnDict.Add("Dupplicate Keys", duplicateKey.Trim)
        Return returnDict
    End Function

    ''' <summary>
    ''' Đưa dữ liệu trong từ điển vào data table
    ''' </summary>
    ''' <param name="sourceDict">Dictionary chứa dữ liệu gốc</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function dictionanyToDataTable(ByVal sourceDict As Dictionary(Of String, Dictionary(Of String, String))) _
                    As DataTable

        Dim row As DataRow
        Dim childDict As Dictionary(Of String, String)

        'duyệt từ điển và fill data
        'duyệt từ điển cha
        For Each fileName As String In sourceDict.Keys
            'duyệt từ điển con
            childDict = sourceDict.Item(fileName)
            For Each itemName As String In childDict.Keys
                row = returnDt.NewRow()
                row("File") = fileName
                row("ItemName") = itemName
                row("Alias") = childDict.Item(itemName)

                returnDt.Rows.Add(row)
            Next
        Next fileName

        Return returnDt
    End Function
#End Region

#Region "Alias"
    ''' <summary>
    ''' Get alias for item
    ''' </summary>
    ''' <param name="itemName">Item need to get alias</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function getAliasFor(ByVal itemName As String) As String
        Dim returnAlias As String = ""

        If aliasDictionary.ContainsKey(itemName) Then
            returnAlias = aliasDictionary.Item(itemName)
        Else
            returnAlias = ""
        End If
        Return returnAlias
    End Function

    ''' <summary>
    ''' Load danh sách alias từ file cấu hình
    ''' </summary>
    ''' <param name="aliasFilePath">Đường dẫn đến file cấu hình</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function loadAliasDictionany(ByVal aliasFilePath As String) As Dictionary(Of String, String)

        Dim aliasDict As New Dictionary(Of String, String)

        'Kiểm tra file alias list có tồn tại hay không
        If My.Computer.FileSystem.FileExists(aliasFilePath) Then
            Dim reader As StreamReader
            Dim readBuffer As String
            Dim splitBuffer As String()


            reader = New StreamReader(aliasFilePath)
            Try
                'đọc file
                While Not reader.EndOfStream
                    readBuffer = reader.ReadLine()
                    splitBuffer = readBuffer.Split(";")
                    aliasDict.Add(correctItemName(splitBuffer(0)), splitBuffer(1))
                End While
            Catch ex As Exception
                'nếu đọc file gặp lỗi thì báo lỗi
                MsgBox("Sai định dạng file alias!", MsgBoxStyle.Critical, "Error")
                aliasDict = Nothing
            End Try
            reader.Close()
        Else 'Nếu file alias list không tồn tại thì báo lỗi
            MsgBox("Không tìm thấy file alias!", MsgBoxStyle.Critical, "Error")
            aliasDict = Nothing
        End If

        Return aliasDict
    End Function

    ''' <summary>
    ''' Khi load file alias, nếu gặp item có tên có dấu gạch dưới thì bỏ dấu gạch dưới
    ''' và chuyển chữ cái tiếp theo thành chữ hoa
    ''' </summary>
    ''' <param name="itemName">Tên item cần sửa</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function correctItemName(ByVal itemName As String) As String
        Dim correctedName As String = ""
        For i As Int16 = 0 To itemName.Length - 1 Step 1
            Dim currentChar As Char = itemName(i)
            If currentChar = "_" Then
                i = i + 1
                If i = itemName.Length Then
                    Exit For
                End If
                currentChar = itemName(i)
                correctedName = correctedName & Char.ToUpper(currentChar)
            Else
                correctedName = correctedName & itemName(i)
            End If

        Next
        Return correctedName
    End Function
#End Region

#Region "Cấu hình"
    Public Sub loadConfiguration()
        config = New Dictionary(Of String, String)

        'Kiểm tra file alias list có tồn tại hay không
        If My.Computer.FileSystem.FileExists(CONFIG_FILE_NAME) Then
            Dim reader As StreamReader
            Dim readBuffer As String

            reader = New StreamReader(CONFIG_FILE_NAME)
            Try
                Dim exception As Char

                'File Selector
                readBuffer = reader.ReadLine()
                exception = readBuffer(0)

                config.Add(FILE_SELECTOR, readBuffer)

                'Seek pattern
                readBuffer = reader.ReadLine()
                exception = readBuffer(0)
                config.Add(SEEK_PATTERN, readBuffer)

                'File Selector
                readBuffer = reader.ReadLine()
                exception = readBuffer(0)
                config.Add(END_SEEK_PATTERN, readBuffer)

                'File Selector
                readBuffer = reader.ReadLine()
                exception = readBuffer(0)
                config.Add(ALIAS_FILE_NAME, readBuffer)

                'File Selector
                readBuffer = reader.ReadLine()
                exception = readBuffer(0)
                config.Add(RAW_ENTRY, readBuffer)
                Exit Sub
            Catch ex As Exception
                'nếu đọc file gặp lỗi thì báo lỗi
                MsgBox("Sai định dạng file cấu hình!", MsgBoxStyle.Critical, "Error")
            End Try
            reader.Close()
        Else 'Nếu file alias list không tồn tại thì báo lỗi
            MsgBox("Không tìm thấy file cấu hình!", MsgBoxStyle.Critical, "Error")
        End If

        Me.Close()
    End Sub
#End Region
End Class
